package yxy.game.pm2.module.plainsarena;

import java.util.*;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.TypeReference;
import jodd.util.StringUtil;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;

import org.redisson.api.RMap;
import yxy.apple.logger.Logger;
import yxy.apple.util.RandomStringUtility;
import yxy.apple.util.RandomUtility;
import yxy.cherry.battle.Team;
import yxy.cherry.battle.module.Position;
import yxy.cherry.battle.module.record.result.BattleResult;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.function;
import yxy.cherry.data.bean.plainsarena;
import yxy.cherry.data.bean.plainsarenarankreward;
import yxy.cherry.data.bean.plainsarenareward;
import yxy.cherry.data.bean.plainsarenarobot;
import yxy.cherry.data.bean.plainsarenasignreward;
import yxy.cherry.data.function.Function;
import yxy.cherry.data.string.GameString;
import yxy.cherry.game.base.redis.RedisManager;
import yxy.cherry.game.base.redis.RedisType;
import yxy.game.pm2.Result;
import yxy.game.pm2.bean.*;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.area.AreaBean;
import yxy.game.pm2.bean.area.AreaGroupBean;
import yxy.game.pm2.bean.currency.Currencies;
import yxy.game.pm2.bean.currency.CurrencyNotEnoughException;
import yxy.game.pm2.bean.currency.CurrencyType;
import yxy.game.pm2.bean.module.rank.RankEntry;
import yxy.game.pm2.bean.mq.CCReason;
import yxy.game.pm2.bean.pubsub.ArenaRankPublisher;
import yxy.game.pm2.message.BattleMessage;
import yxy.game.pm2.message.FormatMessage;
import yxy.game.pm2.message.HeroMessage;
import yxy.game.pm2.message.PlainsArenaMessage;
import yxy.game.pm2.message.PlayerMessage;
import yxy.game.pm2.module.CurrencyHandle;
import yxy.game.pm2.module.arena.RankArena;
import yxy.game.pm2.module.battle.*;
import yxy.game.pm2.module.hero.FormatHandle;
import yxy.game.pm2.module.hero.HeroHandle;
import yxy.game.pm2.module.mail.MailHandle;
import yxy.game.pm2.module.mail.MailTypeEnum;
import yxy.game.pm2.module.niubee.NiuBeeModule;
import yxy.game.pm2.module.plainsarena.PlainsArenaRecord.RecordPlayerInfo;
import yxy.game.pm2.module.stat.StatHandle;

public class PlainsArenaHandle {
    private static final Logger logger = Logger.create(PlainsArenaHandle.class);


    // 界面===========================================================================

    public Result mainInfo(String playerCode, PlainsArenaMessage.PlainsArenaMainResponse.Builder response) {
        DateTime now = DateTime.now();
        DateTime updateTime = PlainsArenaHandle.updateTime(now);

        PlayerBean playerBean = PlayerBean.get(playerCode);
        ServerBean serverBean = ServerBean.get(playerBean.getServerId());
        AreaBean areaBean = AreaBean.get(serverBean.getAreaId());

        PlainsArenaModule module = PlainsArenaModule.get(areaBean.getGroupId());
        boolean isOpen = module.isOpening();
        PlainsArenaPlayerModule playerModule = PlainsArenaPlayerModule.get(playerCode);
        if (playerModule == null) {
            response.setOpen(false);
            return Result.ModuleNotOpen;
        }
        if (isOpen) {
            RankPlainsArena rankPlainsArena = new RankPlainsArena(areaBean.getGroupId(), playerModule.getLevel());

            int rank = rankPlainsArena.rank(playerCode);
            if (rank == 0) {
                rankPlainsArena.put(playerCode);
                rank = rankPlainsArena.rank(playerCode);
            }
//            LinkedList<String> list = playerModule.getOppos();
//            if (list.size() < 3) {
//                refreshOppo(playerModule, rank, rankPlainsArena);
//            }
            //每次都刷新
            refreshOppo(playerModule, rank, rankPlainsArena);
            LinkedList<String> list = playerModule.getOppos();
            for (String oppoCode : list) {
                int ranking = rankPlainsArena.rank(oppoCode);
                PlainsArenaMessage.PlainsArenaRank info = info(ranking, oppoCode);
                response.addShow(info);
            }

            response.setRank(rank);
            response.setWin(playerModule.getWins());
        }
        // 原逻辑，挑战使用竞技神石
        //plainsarena data = data(1);
        //long costNumber = Currency.number(playerCode, CurrencyType.forNumber(data.getCosttype()), data.getCostid());
        //response.setItemNum(costNumber);

        response.setOpen(isOpen);
        response.setUpdateTime(updateTime.getMillis());
        response.setLevel(playerModule.getLevel());
        response.setTimes(playerModule.getTimes(playerModule));
        response.setBuyPrice(playerModule.getBuyTimesPrice(playerModule));
        response.setIsFormatInit(playerModule.getIsFormatInit());
        response.setFormatTimes(PlainsArenaPlayerModule.getFormatTimes(playerModule));

        //每个段位最多容纳固定人数，当段位内的人数不满时，玩家可以直接晋级不需要进行挑战赛晋级
        plainsarena data = data(playerModule.getLevel());
        plainsarena nextdata = data(playerModule.getLevel() + 1);
        if (nextdata != null && playerModule.getWins() >= data.getCondition()) {
            RankPlainsArena nextRank = new RankPlainsArena(areaBean.getGroupId(), playerModule.getLevel() + 1);
            if (nextdata.getRankuser() > nextRank.size()) { //下个段位人数不足，直接晋级
                response.setDirectlyPromote(1);
            }
        }

        // 宝箱奖励
        for (String boxCode : playerModule.getBox()) {
            response.addBox(Integer.valueOf(boxCode));
        }
        // 段位奖励
        for (String boxCode : playerModule.getLevelBox()) {
            response.addLevelbox(Integer.valueOf(boxCode));
        }
        response.setSkip(playerModule.isSkip());

        return Result.Success;
    }

    public Result rankInfo(String playerCode, int rank, int level, PlainsArenaMessage.PlainsArenaPlayerInfoResponse.Builder response) {
        PlayerBean playerBean = PlayerBean.get(playerCode);
        ServerBean serverBean = ServerBean.get(playerBean.getServerId());
        AreaBean areaBean = AreaBean.get(serverBean.getAreaId());

        PlainsArenaPlayerModule playerModuleA = PlainsArenaPlayerModule.get(playerCode);
        if (playerModuleA == null) {
            return Result.ModuleNotOpen;
        }
        response.setUsedFormatTimes(playerModuleA.getUsedFormatTimes());
        response.setTimes(playerModuleA.getTimes(playerModuleA));
        response.setBuyPrice(playerModuleA.getBuyTimesPrice(playerModuleA));

        RankPlainsArena rankPlainsArena = new RankPlainsArena(areaBean.getGroupId(), level);
        RankEntry rankEntry = rankPlainsArena.entryByRanking(rank);
        if (rankEntry == null) {
            return Result.PlainsArenaOppoOut;// 对手不存在
        }
        PlainsArenaPlayerModule playerModuleB = PlainsArenaPlayerModule.get(rankEntry.getKey());
        int rankA = rankPlainsArena.rank(playerCode);

        PlayerBean playerA = PlayerBean.get(playerModuleA.getPlayerCode());
        PlayerBean playerB = PlayerBean.get(playerModuleB.getPlayerCode());


        {
            PlainsArenaMessage.PlainsArenaFighter.Builder builder = PlainsArenaMessage.PlainsArenaFighter.newBuilder();
            builder.setNickname(playerA.getName());
            builder.setHead(playerA.getHead());
            builder.setLevel(playerA.getLevel());
            builder.setRank(rankA);
            response.setFighterA(builder);
        }

        {
            PlainsArenaMessage.PlainsArenaFighter.Builder builder = PlainsArenaMessage.PlainsArenaFighter.newBuilder();
            builder.setNickname(playerB.getName());
            builder.setHead(playerB.getHead());
            builder.setLevel(playerB.getLevel());
            builder.setRank(rank);
            response.setFighterB(builder);
        }

        //如果还没初始化过阵容，则先清空旧阵容
        if (playerModuleA.getIsFormatInit() == 0) {
            playerModuleA.getFormat().clear();
            playerModuleA.set();
        }
        //初始化对手的阵容
        PlainsArenaPlayerModule.initFormats(playerModuleB);

        plainsarena data = data(level); //该等级的配置项
        int formatNum = data.getPvptype(); //1v1,2v2,3v3
        FormatMessageEntry entryA = packFormatInfo(playerModuleA, formatNum, false);
        FormatMessageEntry entryB = packFormatInfo(playerModuleB, formatNum, false);

        response.addAllFormatA(entryA.getFormats());
        response.addAllHerosA(entryA.getHeros());
        response.addAllPowerA(entryA.getFormatPower());

        response.addAllFormatB(entryB.getFormats());
        response.addAllHerosB(entryB.getHeros());
        response.addAllPowerB(entryB.getFormatPower());

        return Result.Success;
    }

    public Result promotedInfo(String playerCode, PlainsArenaMessage.PlainsArenaPromotedInfoResponse.Builder response) {
        PlayerBean playerBean = PlayerBean.get(playerCode);
        ServerBean serverBean = ServerBean.get(playerBean.getServerId());
        AreaBean areaBean = AreaBean.get(serverBean.getAreaId());

        PlainsArenaModule module = PlainsArenaModule.get(areaBean.getGroupId());
        if (!module.isOpening()) {
            return Result.PlainsArenaNotOpen;// 活动没有开始
        }

        PlainsArenaPlayerModule playerModule = PlainsArenaPlayerModule.get(playerCode);
        if (playerModule == null) {
            return Result.ModuleNotOpen;
        }
        int nextLevel = playerModule.getLevel() + 1;
        plainsarena nextdata = data(nextLevel);
        if (nextdata == null) {
            return Result.PlainsArenaNoPromoted;// 这个段位没有晋级赛
        }
        RankPlainsArena nextRankPlainsArena = new RankPlainsArena(areaBean.getGroupId(), nextLevel);
        if (nextdata.getRankuser() > nextRankPlainsArena.size()) {
            response.setDirectlyPromote(1); //直接晋级，不需要挑战
            return Result.Success;
        }

        int start = nextRankPlainsArena.size() - 3; //选取该排名的最后3名挑战
        start = start > 0 ? start : 1;
        Collection<RankEntry> entries = nextRankPlainsArena.range(start + 1, nextRankPlainsArena.size());

        playerModule.getOppos().clear();
        entries.forEach(rankEntry -> {
            playerModule.getOppos().add(rankEntry.getKey());
        });

        LinkedList<String> list = playerModule.getOppos();
        for (String oppoCode : list) {
            int ranking = nextRankPlainsArena.rank(oppoCode);
            PlainsArenaMessage.PlainsArenaRank info = info(ranking, oppoCode);
            response.addShow(info);
        }

        return Result.Success;
    }

    public Result promotedInfo_bak(String playerCode, PlainsArenaMessage.PlainsArenaPromotedInfoResponse.Builder response) {
        PlainsArenaPlayerModule playerModule = PlainsArenaPlayerModule.get(playerCode);
        if (playerModule == null) {
            return Result.ModuleNotOpen;
        }

        plainsarena data = data(playerModule.getLevel());
        plainsarenarobot robot = DataCenter.getData(data.getRobotid(), plainsarenarobot.class);

        for (int i = 0; i < robot.getDps().length; i++) {
            response.addPowerB(robot.getDps()[i]);
        }
        for (int i = 0; i < robot.getHeroid().length; i++) {
            int heroId = robot.getHeroid()[i];
            response.addHerosB(heroId);
        }

        return Result.Success;
    }

    /**
     * 战斗记录
     */
    public Result record(String playerCode, PlainsArenaMessage.PlainsArenaRecordResponse.Builder response) {
        List<PlainsArenaRecord> list = PlainsArenaRecord.get(playerCode);
        for (PlainsArenaRecord record : list) {
            RecordPlayerInfo infoA = record.getInfoA();
            RecordPlayerInfo infoB = record.getInfoB();
            if (infoA == null || infoB == null) continue;

            PlayerBean playerA = PlayerBean.get(infoA.getPlayerCode());
            PlayerBean playerB = PlayerBean.get(infoB.getPlayerCode());
            if (playerA == null || playerB == null) continue;

            PlainsArenaMessage.PlainsArenaRecord.Builder builder = PlainsArenaMessage.PlainsArenaRecord.newBuilder();
            builder.setCode(record.getCode());
            builder.setDate(record.getDate().getMillis());
            builder.setWin(record.isWin());
            {
                PlainsArenaMessage.PlainsArenaFighter.Builder fighterA = packFighter(playerA);
                fighterA.setRank(infoA.getRank());
                builder.setFighterA(fighterA);
            }

            {
                PlainsArenaMessage.PlainsArenaFighter.Builder fighterB = packFighter(playerB);
                fighterB.setRank(infoB.getRank());
                builder.setFighterB(fighterB);
            }

            response.addRecords(builder);
        }
        return Result.Success;
    }

    public Result recordInfo(String playerCode, String code, PlainsArenaMessage.PlainsArenaRecordInfoResponse.Builder response) {
        List<PlainsArenaRecord> list = PlainsArenaRecord.get(playerCode);
        for (PlainsArenaRecord record : list) {
            if (record.getCode().equals(code)) {
                for (String recordCode : record.getRecordCodes()) {
                    BattleRecord battleRecord = BattleRecord.getv(recordCode);
                    if (battleRecord == null) {
                        continue;
                    }
                    response.addPlayback(new BattleHandle().playback(battleRecord));
                }
                return Result.Success;
            }
        }
        return Result.PlainsArenaRecordOut;// 战斗记录不存在了
    }

    public Result refresh(String playerCode, PlainsArenaMessage.PlainsArenaRefreshResponse.Builder response) {
        PlayerBean playerBean = PlayerBean.get(playerCode);
        ServerBean serverBean = ServerBean.get(playerBean.getServerId());
        AreaBean areaBean = AreaBean.get(serverBean.getAreaId());

        PlainsArenaModule module = PlainsArenaModule.get(areaBean.getGroupId());
        if (!module.isOpening()) {
            return Result.PlainsArenaNotOpen;// 活动没有开始
        }

        PlainsArenaPlayerModule playerModule = PlainsArenaPlayerModule.get(playerCode);
        if (playerModule == null) {
            return Result.ModuleNotOpen;
        }
        RankPlainsArena rankPlainsArena = new RankPlainsArena(areaBean.getGroupId(), playerModule.getLevel());
        int rank = rankPlainsArena.rank(playerCode);
        if (rank == 0) {
            rankPlainsArena.put(playerCode);
        }
        refreshOppo(playerModule, rank, rankPlainsArena);
        LinkedList<String> list = playerModule.getOppos();
        for (String oppoCode : list) {
            int ranking = rankPlainsArena.rank(oppoCode);
            PlainsArenaMessage.PlainsArenaRank info = info(ranking, oppoCode);
            response.addShow(info);
        }

//		Collection<RankEntry> entrys = rankPlainsArena.pick(list);
//		for (RankEntry entry : entrys) {
//			int ranking = rankPlainsArena.rank(entry.getKey());
//			PlainsArenaMessage.PlainsArenaRank info = info(ranking, entry);
//			response.addShow(info);
//		}

        return Result.Success;
    }

    public Result formatInfo(String playerCode, PlainsArenaMessage.PlainsArenaFormatUIResponse.Builder response) {
        PlainsArenaPlayerModule playerModule = PlainsArenaPlayerModule.get(playerCode);
        if (playerModule == null) {
            return Result.ModuleNotOpen;
        }

        FormatMessageEntry entry = packFormatInfo(playerModule, 0, true);

        NiuBeeModule niubeeModule = NiuBeeModule.get(playerCode);

        response.setNbAct(niubeeModule.getProgress());
        response.setNbLevel(niubeeModule.getLevel());

        response.addAllFormat(entry.getFormats());
        response.addAllHeros(entry.getHeros());
        return Result.Success;
    }

    public Result formatSet(String playerCode, List<FormatMessage.Format> formatList, PlainsArenaMessage.PlainsArenaFormatResponse.Builder response) {
        PlainsArenaPlayerModule playerModule = PlainsArenaPlayerModule.get(playerCode);
        if (playerModule == null) {
            return Result.ModuleNotOpen;
        }
        int ftimes = PlainsArenaPlayerModule.getFormatTimes(playerModule);
        if (PlainsArenaPlayerModule.getFormatTimes(playerModule) < 1) {
            return Result.PlainsArenaNoFormatTimes; //当天阵容调整次数用完
        }

        if (formatList.size() < 3) {
            return Result.PlainsArenaFormatLess;// 需要保存三份阵容
        }
        Map<Integer, Hero> map = new HashMap<>();
        ArrayList<Format> formats = new ArrayList<>();
        int index = 0; //第几队
        for (FormatMessage.Format formatrequest : formatList) {
            Format format = new Format();
            Result result = checkFormat(index, playerModule, format, null, map, formatrequest);
            if (!result.equals(Result.Success)) {
                return result;
            }
            formats.add(format);
            index ++;
        }


        try {
            if (playerModule.tryLock()) {
                playerModule.getFormat().clear();
                playerModule.getFormat().addAll(formats);
                playerModule.setUsedFormatTimes(playerModule.getUsedFormatTimes() + 1); //调整阵容次数
                playerModule.setIsFormatInit(1);
                playerModule.set();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            playerModule.unlock();
        }
        return Result.Success;

    }

    private Result checkFormat(int index, PlainsArenaPlayerModule playerModule, Format format, Map<String, Hero> all, Map<Integer, Hero> map, FormatMessage.Format formatrequest) {
        String playerCode = playerModule.getPlayerCode();
        FormatHandle formatHandle = new FormatHandle();
        plainsarena config = DataCenter.getData(String.valueOf(playerModule.getLevel()), plainsarena.class); //配置表
        int[] formatnum = config.getFormatnum(); //布阵队伍人数
        if (index >= config.getPvptype()) return Result.PlainsArenaFormatException; //阵容设置异常
        int formatMaxNum = formatnum[index];
        int heroNum = 0; //该队伍布阵的英雄数

        if (!StringUtil.isEmpty(formatrequest.getFU())) {
            format.setFu(formatrequest.getFU());
            heroNum ++;
        }
        if (!StringUtil.isEmpty(formatrequest.getFM())) {
            format.setFm(formatrequest.getFM());
            heroNum ++;
        }
        if (!StringUtil.isEmpty(formatrequest.getFD())) {
            format.setFd(formatrequest.getFD());
            heroNum ++;
        }
        if (!StringUtil.isEmpty(formatrequest.getBU())) {
            format.setBu(formatrequest.getBU());
            heroNum ++;
        }
        if (!StringUtil.isEmpty(formatrequest.getBM())) {
            format.setBm(formatrequest.getBM());
            heroNum ++;
        }
        if (!StringUtil.isEmpty(formatrequest.getBD())) {
            format.setBd(formatrequest.getBD());
            heroNum ++;
        }
        int nb = formatrequest.getNB();
        format.setNb(nb);
        if (index <= config.getPvptype() && heroNum < 1) return Result.PlainsArenaFormatLess; //需要上阵的阵容不全
        if (heroNum > formatMaxNum) return Result.PlainsArenaFormatNumOverstep; //超出该队伍数量限制

        try {
            formatHandle.checkFormat(playerCode, format.getFu(), map);
            formatHandle.checkFormat(playerCode, format.getFm(), map);
            formatHandle.checkFormat(playerCode, format.getFd(), map);
            formatHandle.checkFormat(playerCode, format.getBu(), map);
            formatHandle.checkFormat(playerCode, format.getBm(), map);
            formatHandle.checkFormat(playerCode, format.getBd(), map);
        } catch (Exception e) {
            return Result.FormatSameHero;// 不能上阵同样的武将
        }

        // 检查神器
        if (format.getNb() > 0) {
            NiuBeeModule niubeeModule = NiuBeeModule.get(playerCode);
            if (niubeeModule.getProgress() < format.getNb()) {
                return Result.FormatNiubeeError;// 神器设置错误
            }
        }

        return Result.Success;
    }

    private PlainsArenaMessage.PlainsArenaRank info(int rank, String playerCode) {
        PlainsArenaMessage.PlainsArenaRank.Builder rankInfo = PlainsArenaMessage.PlainsArenaRank.newBuilder();
        PlayerBean player = PlayerBean.get(playerCode);
        PlainsArenaPlayerModule playerModule = PlainsArenaPlayerModule.get(playerCode);
        PlainsArenaPlayerModule.initFormats(playerModule);

        PlayerMessage.PlayerSimpleInfo.Builder simpleInfoBuilder = PlayerMessage.PlayerSimpleInfo.newBuilder();
        simpleInfoBuilder.setPlayerCode(playerCode);
        simpleInfoBuilder.setNickname(player.getName());
        simpleInfoBuilder.setHead(player.getHead());
        simpleInfoBuilder.setAvatar(player.getAvatar());
        //builder.setPower(player.getPower());
        simpleInfoBuilder.setServerId(player.getServerId());

        //重新计算战力
        plainsarena config = DataCenter.getData(String.valueOf(playerModule.getLevel()), plainsarena.class); //配置表
        FormatMessageEntry entry = packFormatInfo(playerModule, config.getPvptype(), false);
        long total = 0;
        for (long power : entry.getFormatPower()) {
            total += power;
        }
        simpleInfoBuilder.setPower(total);
        logger.info("total power:%s:%s", total, simpleInfoBuilder.getPower());

        rankInfo.setRank(rank);
        rankInfo.setPlayerInfo(simpleInfoBuilder);
        rankInfo.setLevel(playerModule.getLevel());



        return rankInfo.build();
    }

    private void refreshOppo(PlainsArenaPlayerModule playerModule, int rank, RankPlainsArena rankPlainsArena) {
        try {
            if (playerModule.tryLock()) {
                LinkedList<Integer> list = randomMatch(rank, rankPlainsArena.size());
                Collection<RankEntry> entrys = rankPlainsArena.pick(list);
                LinkedList<String> oppos = new LinkedList<>();
                for (RankEntry entry : entrys) {
                    oppos.add(entry.getKey());
                }
                playerModule.setOppos(oppos);
                playerModule.set();
            }
        } catch (Exception e) {
        } finally {
            playerModule.unlock();
        }
    }

    private LinkedList<Integer> randomMatch(int rank, int maxRank) {
        //logger.info("randomMatch:%s,%s", rank, maxRank);
        LinkedList<Integer> list = new LinkedList<>();
        //选择当前排名的前10 ~ 后10 之间的随机
        int min = rank - 10;
        int max = rank + 10;
        min = min < 1 ? 1 : min;
        max = max > maxRank ? maxRank : max;
        int len = max - min + 1;
        // logger.info("randomMatch,min:%s,max:%s,len:%s", min, max, len);
        if (len <= 4) { //如果排上只有其它3个对手（包含自己有4个）
            for (int i = 1; i <= len; i++) {
                if (i != rank) list.addFirst(i);
            }
            return list;
        }

        //多于3个对手
        int times = 0;
        while (true) {
            int r = RandomUtility.nextInt(min, max + 1);
            if (!list.contains(r) && r != rank) {
                list.addFirst(r);
                times += 1;
                if (times >= 4) break;
            }
        }
        //System.out.println(JSON.toJSONString(list));

        return list;
    }

    private LinkedList<Integer> randomMatch_bak(int rank) {
        LinkedList<Integer> list = new LinkedList<>();
        if (rank <= 3) {
            for (int r = 3; r > 0; r--) {
                list.addFirst(r);
            }
            return list;
        }
        int min = rank / 100;
        int max = rank / 10;
        min = min < 1 ? 1 : min;
        max = max < 1 ? 1 : max;
        for (int i = 0; i < 3; i++) {
            int r = RandomUtility.nextInt(min, max + 1);
            rank -= r;
            list.addFirst(rank);
        }

        return list;
    }

    private plainsarena data(int level) {
        return DataCenter.getData(String.valueOf(level), plainsarena.class);
    }

    // 战斗处理===========================================================================
    private String code() {
        return BattleType.PLAINSARENA.name();
    }

    // 挑战
    public Result battleResponseExecute(String playerCode, int rankB, boolean skip, PlainsArenaMessage.PlainsArenaChanllengeResponse.Builder response) {
        if (rankB <= 0) {
            return Result.ParamError;
        }

        PlayerBean playerBean = PlayerBean.get(playerCode);
        ServerBean serverBean = ServerBean.get(playerBean.getServerId());
        AreaBean areaBean = AreaBean.get(serverBean.getAreaId());

        PlainsArenaModule module = PlainsArenaModule.get(areaBean.getGroupId());
        if (!module.isOpening()) {
            return Result.PlainsArenaNotOpen;// 活动没有开始
        }
        DateTime now = DateTime.now();

        PlainsArenaPlayerModule playerModuleA = PlainsArenaPlayerModule.get(playerCode);
        if (playerModuleA == null) {
            return Result.ModuleNotOpen;
        }

        //还未调整过阵容
        if (playerModuleA.getIsFormatInit() == 0) {
            return Result.PlainsArenaNotInitFormat;
        }

        RankPlainsArena rankPlainsArena = new RankPlainsArena(areaBean.getGroupId(), playerModuleA.getLevel());

        int rankA = rankPlainsArena.rank(playerCode);
        if (rankA == 0) {
            rankPlainsArena.put(playerCode);
            rankA = rankPlainsArena.rank(playerCode);
        }

        RankEntry entryA = rankPlainsArena.entryByRanking(rankA);

        RankEntry entryB = rankPlainsArena.entryByRanking(rankB);
        if (entryB == null) {
            return Result.PlainsArenaOppoOut;// 对手不存在
        }

        if (rankB == rankA) {
            // 排名比玩家低 或 同玩家排名一样（玩家本人）
            return Result.PlainsArenaCantChanllenge;// 不能挑战这个位置的玩家
        }

        PlainsArenaPlayerModule playerModuleB = PlainsArenaPlayerModule.get(entryB.getKey());

        plainsarena data = data(playerModuleA.getLevel());
        int battleNum = data.getPvptype();
        for (int i = 0; i < battleNum; i++) {
            TeamModule teamA = team(playerModuleA, i);
            if (teamA == null) {
                return Result.PlainsArenaFormatLess;
            }
        }

        if (playerModuleA.getTimes(playerModuleA) < 1) { //挑战次数不足，需要购买
            Result result = new PlainsArenaHandle().buyTimes(playerModuleA, 1);
            if (!Result.Success.equals(result)) return result;
        }
        playerModuleA.useTimes(playerModuleA,1); //消耗挑战次数

//        try {
//            Currency cost = Currency.create(data.getCosttype(), data.getCostid(), data.getCostnum());
//            new CurrencyHandle().cost(playerCode, CCReason.中原擂台, cost);
//        } catch (CurrencyNotEnoughException e) {
//            return new Result(Result.CostFail, e.getType().getNumber(), e.getDataId());// 消费不足
//        }

        boolean isAllWin = false;
        int winNum = 0;
        ArrayList<BattleModule> battleList = new ArrayList<>();
        for (int i = 0; i < battleNum; i++) {
            BattleModule battleModule = BattleModule.create(playerCode);
            battleModule.setType(BattleType.PLAINSARENA);
            battleModule.setCode(code());
            battleList.add(battleModule);
            // 玩家的team
            TeamModule teamA = team(playerModuleA, i);
            if (teamA == null) {
                return Result.DataError;
            }
            // 对手的team
            TeamModule teamB = team(playerModuleB, i);

            //todo 修改登录时间，3天后自动清除缓存
            StatHandle.stat_用户登录状态更新(playerModuleB.getPlayerCode());

            boolean isWin = battleHandle(battleModule, teamA, teamB);
            if (isWin) {
                winNum++;
            }
            if (winNum >= (battleNum / 2 + (battleNum % 2))) {
                isAllWin = true;
                break;
            }
        }

        Currencies rewards = new Currencies();
        if (isAllWin) {
            long diff = entryA.getValue() - entryB.getValue();
            if (diff == 0) { //bugfix,有可能score值一样
                entryB.setValue(entryB.getValue() + 1);
            }
            if (diff >= 0) {
                // 交换排名
                rankPlainsArena.remove(entryA.getKey());
                rankPlainsArena.remove(entryB.getKey());
                rankPlainsArena.put(entryA.getKey(), entryB.getValue());
                rankPlainsArena.put(entryB.getKey(), entryA.getValue());
            }

            rewards.add(Currency.create(data.getWinrewardtype(), data.getWinrewardid(), data.getWinrewardnum()));
        } else {
            rewards.add(Currency.create(data.getLoserewardtype(), data.getLoserewardid(), data.getLosewinrewardnum()));
        }
        // 处理奖励
        new CurrencyHandle().addCurrency(playerCode, CCReason.中原擂台, rewards);

        // 处理录像
        ArrayList<BattleRecord> recordList = new ArrayList<>();
        for (BattleModule battleModule : battleList) {
            if (battleModule.getRecord() == null) {
                continue;
            }
            BattleRecord battleRecord = battleModule.saveRecord(BattleRecord.randomCode(), 1);
            recordList.add(battleRecord);
        }
        PlainsArenaRecord record = new PlainsArenaRecord();
        record.setWin(isAllWin);
        PlayerBean playerA = PlayerBean.get(entryA.getKey());
        PlayerBean playerB = PlayerBean.get(entryB.getKey());
        RecordPlayerInfo infoA = new RecordPlayerInfo();
        infoA.setPlayerCode(playerA.getCode());
        infoA.setLevel(playerA.getLevel());
        infoA.setPower(playerA.getPower());
        infoA.setRank(isAllWin ? rankB : rankA);
        record.setInfoA(infoA);

        RecordPlayerInfo infoB = new RecordPlayerInfo();
        infoB.setPlayerCode(playerB.getCode());
        infoB.setLevel(playerB.getLevel());
        infoB.setPower(playerB.getPower());
        infoB.setRank(isAllWin ? rankA : rankB);

        record.setInfoB(infoB);
        for (BattleRecord battleRecord : recordList) {
            record.getRecordCodes().add(battleRecord.getCode());
        }
        record.setDate(now);
        String code = String.format("plainsRec%s%s", now.toString(DateTimeFormat.forPattern("yyyyMMddHHmmss")), RandomStringUtility.randomAlpha(4));
        record.setCode(code);

        PlainsArenaRecord.add(playerA.getCode(), record);
        PlainsArenaRecord.add(playerB.getCode(), record);

        // 封装消息
        {
            PlainsArenaMessage.PlainsArenaFighter.Builder fighterA = packFighter(playerA);
            PlainsArenaMessage.PlainsArenaFighter.Builder fighterB = packFighter(playerB);

            if (isAllWin && rankA > rankB) {
                fighterA.setRank(rankB);
                fighterB.setRank(-rankA);
            } else {
                fighterA.setRank(rankA);
                fighterB.setRank(rankB);
            }

            for (BattleRecord battleRecord : recordList) {
                BattleMessage.BattleExecuteResponse.Builder builder = BattleMessage.BattleExecuteResponse.newBuilder();
                builder.setPlayback(new BattleHandle().playback(battleRecord));// , team_a, team_b));

                response.addBattleResp(builder);// 录像
            }

            response.setWin(isAllWin);
            response.setLevel(playerModuleA.getLevel());

            response.setFighterA(fighterA);// 进攻方
            response.setFighterB(fighterB);// 防守方

            response.addAllRewards(new CurrencyHandle().packItems(rewards));
        }

        // 刷新对手
        playerModuleA.setWins(playerModuleA.getWins() + (isAllWin ? 1 : 0));
        playerModuleA.setSkip(skip);

        refreshOppo(playerModuleA, isAllWin ? rankB : rankA, rankPlainsArena);
        if (isAllWin) {
            refreshOppo(playerModuleB, rankA, rankPlainsArena);
        }

        return Result.Success;
    }

    /**
     * 晋级战
     */
    public Result battleResponsePromoted(String playerCode, int rankB, PlainsArenaMessage.PlainsArenaChanllengePromotedResponse.Builder response) {
        PlayerBean playerBean = PlayerBean.get(playerCode);
        ServerBean serverBean = ServerBean.get(playerBean.getServerId());
        AreaBean areaBean = AreaBean.get(serverBean.getAreaId());
        boolean isAllWin = false;

        PlainsArenaModule module = PlainsArenaModule.get(areaBean.getGroupId());
        if (!module.isOpening()) {
            return Result.PlainsArenaNotOpen;// 活动没有开始
        }

        PlainsArenaPlayerModule playerModuleA = PlainsArenaPlayerModule.get(playerCode);
        if (playerModuleA == null) {
            return Result.ModuleNotOpen;
        }

        int nextLevel = playerModuleA.getLevel() + 1;
        plainsarena data = data(playerModuleA.getLevel());
        plainsarena nextdata = data(nextLevel);
        if (nextdata == null) {
            return Result.PlainsArenaNoPromoted;// 这个段位没有晋级赛
        }
        if (playerModuleA.getWins() < data.getCondition()) {
            return Result.PlainsArenaCantPromoted;// 晋级条件不足
        }

        RankPlainsArena rankPlainsArena = new RankPlainsArena(areaBean.getGroupId(), playerModuleA.getLevel());
        RankPlainsArena nextRankPlainsArena = new RankPlainsArena(areaBean.getGroupId(), nextLevel);

        Currencies rewards = new Currencies();
        if (nextRankPlainsArena.size() < nextdata.getRankuser()) {
            //下一段位的排名用户不足（有空位），直接晋级，不需要挑战
            isAllWin = true;

            rewards.add(Currency.create(data.getPromotionrewardtype(), data.getPromotionrewardid(), data.getPromotionrewardnum()));
            // 处理奖励
            new CurrencyHandle().addCurrency(playerCode, CCReason.中原擂台, rewards);
            // 段位处理
            rankPlainsArena.remove(playerCode); //旧段位排行榜
            playerModuleA.setLevel(nextdata.getRank());
            playerModuleA.setWins(0);
            playerModuleA.set();
            nextRankPlainsArena.put(playerCode);
            int rank = nextRankPlainsArena.rank(playerCode);
            refreshOppo(playerModuleA, rank, nextRankPlainsArena);

            if (rewards.size() > 0) {
                response.addAllRewards(new CurrencyHandle().packItems(rewards));
            }
        } else {
            //选下一个段位的对手挑战
            RankEntry entryB = nextRankPlainsArena.entryByRanking(rankB);
            if (entryB == null) {
                return Result.PlainsArenaOppoOut;// 对手不存在
            }
            PlainsArenaPlayerModule playerModuleB = PlainsArenaPlayerModule.get(entryB.getKey());

            int battleNum = nextdata.getPvptype();
            for (int i = 0; i < battleNum; i++) {
                TeamModule teamA = team(playerModuleA, i);
                if (teamA == null) {
                    return Result.PlainsArenaFormatLess;
                }
            }

            int winNum = 0;
            ArrayList<BattleModule> battleList = new ArrayList<>();
            for (int i = 0; i < battleNum; i++) {
                BattleModule battleModule = BattleModule.create(playerCode);
                battleModule.setType(BattleType.PLAINSARENA);
                battleModule.setCode(code());
                battleList.add(battleModule);
                // 玩家的team
                TeamModule teamA = team(playerModuleA, i);
                if (teamA == null) {
                    return Result.DataError;
                }
                // 对手的team
                TeamModule teamB = team(playerModuleB, i);
                if (teamB == null) {
                    return Result.DataError;
                }

                boolean isWin = battleHandle(battleModule, teamA, teamB);
                if (isWin) {
                    winNum++;
                }
                if (winNum >= (battleNum / 2 + (battleNum % 2))) {
                    isAllWin = true;
                    break;
                }
            }

            // 封装消息
            {
                PlayerBean playerA = PlayerBean.get(playerCode);
                PlayerBean playerB = PlayerBean.get(playerModuleB.getPlayerCode());
                PlainsArenaMessage.PlainsArenaFighter.Builder fighterA = packFighter(playerA);
                PlainsArenaMessage.PlainsArenaFighter.Builder fighterB = packFighter(playerB);

                for (BattleRecord battleRecord : battleList) {
                    BattleMessage.BattleExecuteResponse.Builder builder = BattleMessage.BattleExecuteResponse.newBuilder();
                    builder.setPlayback(new BattleHandle().playback(battleRecord));// , team_a, team_b));

                    response.addBattleResp(builder);// 录像
                }

                response.setFighterA(fighterA);// 进攻方
                response.setFighterB(fighterB);// 防守方
            }

            if (isAllWin) {
                rewards.add(Currency.create(data.getPromotionrewardtype(), data.getPromotionrewardid(), data.getPromotionrewardnum()));
                // 处理奖励
                new CurrencyHandle().addCurrency(playerCode, CCReason.中原擂台, rewards);
                if (rewards.size() > 0) {
                    response.addAllRewards(new CurrencyHandle().packItems(rewards));
                }

                // 打败对手后，和对手交换【段位和排名】
                int rankA = rankPlainsArena.rank(playerModuleA.getPlayerCode());
                RankEntry entryA = rankPlainsArena.entryByRanking(rankA);
                rankPlainsArena.remove(playerModuleA.getPlayerCode());
                nextRankPlainsArena.remove(playerModuleB.getPlayerCode());

                nextRankPlainsArena.put(entryA.getKey(), entryB.getValue()); //交换
                playerModuleA.setLevel(nextdata.getRank());
                playerModuleA.setWins(0);
                playerModuleA.set();
                refreshOppo(playerModuleA, rankB, nextRankPlainsArena);

                rankPlainsArena.put(entryB.getKey(), entryA.getValue()); //交换
                playerModuleB.setLevel(data.getRank());
                playerModuleB.setWins(0);
                playerModuleB.set();
                refreshOppo(playerModuleB, rankA, rankPlainsArena);
            } else {
                //晋级失败，重置胜利次数，重新挑战
                playerModuleA.setWins(0);
                playerModuleA.set();
            }
        }


        response.setWin(isAllWin);
        response.setLevel(playerModuleA.getLevel());

        return Result.Success;
    }

    /**
     * 晋级战
     */
    public Result battleResponsePromoted_bak(String playerCode, PlainsArenaMessage.PlainsArenaChanllengePromotedResponse.Builder response) {
        PlayerBean playerBean = PlayerBean.get(playerCode);
        ServerBean serverBean = ServerBean.get(playerBean.getServerId());
        AreaBean areaBean = AreaBean.get(serverBean.getAreaId());

        PlainsArenaModule module = PlainsArenaModule.get(areaBean.getGroupId());
        if (!module.isOpening()) {
            return Result.PlainsArenaNotOpen;// 活动没有开始
        }

        PlainsArenaPlayerModule playerModuleA = PlainsArenaPlayerModule.get(playerCode);
        if (playerModuleA == null) {
            return Result.ModuleNotOpen;
        }

        plainsarena data = data(playerModuleA.getLevel());
        plainsarena nextdata = data(playerModuleA.getLevel() + 1);
        plainsarenarobot robotdata = DataCenter.getData(data.getRobotid(), plainsarenarobot.class);
        if (nextdata == null || robotdata == null) {
            return Result.PlainsArenaNoPromoted;// 这个段位没有晋级赛
        }
        if (playerModuleA.getWins() < data.getCondition()) {
            return Result.PlainsArenaCantPromoted;// 晋级条件不足
        }
        int battleNum = data.getPvptype();
        for (int i = 0; i < battleNum; i++) {
            TeamModule teamA = team(playerModuleA, i);
            if (teamA == null) {
                return Result.PlainsArenaFormatLess;
            }
        }

        try {
            Currency cost = Currency.create(nextdata.getCosttype(), nextdata.getCostid(), nextdata.getCostnum());
            new CurrencyHandle().cost(playerCode, CCReason.中原擂台, cost);
        } catch (CurrencyNotEnoughException e) {
            return new Result(Result.CostFail, e.getType().getNumber(), e.getDataId());// 消费不足
        }
        boolean isAllWin = false;
        int winNum = 0;
        ArrayList<BattleModule> battleList = new ArrayList<>();
        for (int i = 0; i < battleNum; i++) {
            BattleModule battleModule = BattleModule.create(playerCode);
            battleModule.setType(BattleType.PLAINSARENA);
            battleModule.setCode(code());
            battleList.add(battleModule);
            // 玩家的team
            TeamModule teamA = team(playerModuleA, i);
            if (teamA == null) {
                return Result.DataError;
            }
            // 对手的team
            TeamModule teamB = teamPromoted(data, i);

            boolean isWin = battleHandle(battleModule, teamA, teamB);
            if (isWin) {
                winNum++;
            }
            if (winNum >= (battleNum / 2 + (battleNum % 2))) {
                isAllWin = true;
                break;
            }
        }

        Currencies rewards = new Currencies();
        if (isAllWin) {
            rewards.add(Currency.create(data.getPromotionrewardtype(), data.getPromotionrewardid(), data.getPromotionrewardnum()));
            // 处理奖励
            new CurrencyHandle().addCurrency(playerCode, CCReason.中原擂台, rewards);

            RankPlainsArena rankPlainsArena = new RankPlainsArena(areaBean.getGroupId(), playerModuleA.getLevel());
            rankPlainsArena.remove(playerCode);

            playerModuleA.setLevel(nextdata.getRank());
            playerModuleA.setWins(0);
            RankPlainsArena rankPromote = new RankPlainsArena(areaBean.getGroupId(), nextdata.getRank());
            rankPromote.put(playerCode);
            int rank = rankPromote.rank(playerCode);
            refreshOppo(playerModuleA, rank, rankPromote);
        }

        // 封装消息
        {
            PlayerBean playerA = PlayerBean.get(playerCode);
            PlainsArenaMessage.PlainsArenaFighter.Builder fighterA = packFighter(playerA);
            PlainsArenaMessage.PlainsArenaFighter.Builder fighterB = packPromoted(robotdata);

            for (BattleRecord battleRecord : battleList) {
                BattleMessage.BattleExecuteResponse.Builder builder = BattleMessage.BattleExecuteResponse.newBuilder();
                builder.setPlayback(new BattleHandle().playback(battleRecord));// , team_a, team_b));

                response.addBattleResp(builder);// 录像
            }

            response.setWin(isAllWin);
            response.setLevel(playerModuleA.getLevel());

            response.setFighterA(fighterA);// 进攻方
            response.setFighterB(fighterB);// 防守方

            if (rewards.size() > 0) {
                response.addAllRewards(new CurrencyHandle().packItems(rewards));
            }
        }

        return Result.Success;
    }

    private PlainsArenaMessage.PlainsArenaFighter.Builder packFighter(PlayerBean playerBean) {
        PlainsArenaMessage.PlainsArenaFighter.Builder builder = PlainsArenaMessage.PlainsArenaFighter.newBuilder();
        builder.setServerId(playerBean.getServerId());
        builder.setNickname(playerBean.getName());
        builder.setHead(playerBean.getHead());
        builder.setHeadFrame(playerBean.getHeadframe());
        builder.setLevel(playerBean.getLevel());
        return builder;
    }

    private PlainsArenaMessage.PlainsArenaFighter.Builder packPromoted(plainsarenarobot data) {
        PlainsArenaMessage.PlainsArenaFighter.Builder builder = PlainsArenaMessage.PlainsArenaFighter.newBuilder();
        builder.setNickname(data.getName());
        builder.setHead(data.getHeadid());
        builder.setLevel(data.getLevel());
        return builder;
    }

    private boolean battleHandle(BattleModule battleModule, TeamModule teamA, TeamModule teamB) {
        if (teamA == null) {
            return false;
        }
        battleModule.setTeamA(teamA);
        if (teamB == null) {
            return true;
        }
        battleModule.setTeamB(teamB);

        BattleHandle battleHandle = new BattleHandle();

        Team team_a = teamA.team(true);
        Team team_b = teamB.team(false);
        team_a.setTeam对手(team_b);
        team_b.setTeam对手(team_a);

        // 处理战斗
        battleHandle.battleExecute(battleModule, team_a, team_b, 20);

        boolean isWin = battleModule.getBattleResult().equals(BattleResult.LEFT_WIN);

        return isWin;
    }

    private TeamModule team(PlainsArenaPlayerModule playerModule, int i) {
        String playerCode = playerModule.getPlayerCode();
        Format format = playerModule.getFormat().get(i);

        TeamModule team = new BattleHandle().teamPlayer(playerCode, format);
        if (team.fighters().size() <= 0) {
            return null;
        }
        return team;
    }

    private TeamModule teamPromoted(plainsarena data, int index) {
        plainsarenarobot robotdata = DataCenter.getData(data.getRobotid(), plainsarenarobot.class);
        if (robotdata == null) {
            return null;
        }
        TeamModule team = new TeamModule();
        int n = 6 * index;

        for (int i = n; i < robotdata.getHeroid().length && i < n + 6; i++) {
            Position position = Position.forValue((i % 6) + 1);
            int heroid = robotdata.getHeroid()[i];
            int level = robotdata.getGrade()[i];
            int anger = robotdata.getInitialangerup()[i];
            int stage = 0;
            int star = 0;
            if (heroid == -1) continue;

            //如果找不到heroid默认不变  stage和star为0
            HashMap<String, Integer> map = BattleHandle.addStarAndStage(heroid, stage, star, level);
            heroid = map.get("heroid");
            stage = map.get("stage");
            star = map.get("star");

            FighterModule fighterModule = FighterModule.create(heroid, level, stage, star, anger);
            fighterModule.setProperty(PropertyModule.create(BattleHandle.getOppositePropertyData(heroid, level, stage, star, anger)));

            team.addfighter(position, fighterModule);
        }
        // 神器
        WeaponModule weapon = WeaponModule.create(robotdata.getWeapondataid()[index], robotdata.getWeaponlv()[index], 0, 0,
                robotdata.getWeaponskilllv()[index]);
        team.setWeapon(weapon);

        // 信息
        team.setName(robotdata.getName());
        team.setHead(robotdata.getHeadid());
        team.setLevel(robotdata.getPlayerlv());
        team.setPower(robotdata.getDps()[index]);

        return team;
    }

    // 时间控制===========================================================================

    /**
     * 状态更新
     */
    public void update() {
        Collection<AreaGroupBean> areaGroupBeans = AreaGroupBean.all(); //战区列表
        for (AreaGroupBean areaGroupBean : areaGroupBeans) {
            DateTime now = DateTime.now();
            PlainsArenaModule module = PlainsArenaModule.get(areaGroupBean.getGroupId());
            boolean preState = module.isOpening();
            boolean nowState = isOpen(now);
            if (preState == nowState) {
                continue;
            }
            boolean rewardRank = false;
            try {
                if (module.tryLock()) {
//				module.setOpening(nowState);
                    if (nowState) {
                        open(areaGroupBean.getGroupId(), module, now);
                    } else {
                        // 关闭活动 派发邮件奖励
                        settle(module);
                        rewardRank = true;
                    }
                    module.set();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                module.unlock();
            }
            if (rewardRank) {
                rewardRank(areaGroupBean.getGroupId());
            }
        }
    }

    public static DateTime updateTime(DateTime time) {
        int week = time.getDayOfWeek();// 星期
        switch (week) {
            case 7:
                if (time.getHourOfDay() >= 23) {
                    return time.withTimeAtStartOfDay().plusDays(1);
                }
        }
        return time.withTimeAtStartOfDay().withDayOfWeek(7).plusHours(23);
    }

    public static boolean isOpen(DateTime time) {
        if (time == null) {
            return false;
        }
        int week = time.getDayOfWeek();// 星期
        switch (week) {
            case 7:
                return time.getHourOfDay() < 23;
        }
        return true;
    }

    // XXX TEST 短时测试
//	public static boolean isOpen(DateTime time) {
//		if (time == null) {
//			return false;
//		}
//		// 每天0~23一轮
//		return time.getHourOfDay() < 23;
////		return true;
//	}

    private void open(int areaGroupId, PlainsArenaModule module, DateTime time) {
        System.err.println("中原擂台活动准备！！！" + DateTime.now().toString());
        function funcion = DataCenter.getData(Function.中原擂台.getId(), function.class);
        AreaGroupBean areaGroupBean = AreaGroupBean.get(areaGroupId);

        boolean open = false;
        Map<String, plainsarena> all = DataCenter.getAllData(plainsarena.class);
        for (plainsarena data : all.values()) {
            int level = data.getRank();
            RankPlainsArena rankPlainsArena = new RankPlainsArena(areaGroupId, level);
            rankPlainsArena.clear(); //清除排行榜数据
            if (level == 1) {
                ArrayList<String> areaIds = areaGroupBean.getAreaList();
                for (String areaId : areaIds) {
                    AreaBean areaBean = AreaBean.get(Integer.valueOf(areaId));
                    if (areaBean.getWorldLevel() < funcion.getWordlv()) {
                        System.err.println("中原擂台活动区域" + areaBean.getAreaId() + "世界等级不足无法参加");
                        continue;// 世界等级不足该区域不参加
                    }

                    int num = 0;
                    RankArena rankArena = new RankArena(areaBean); //判断竞技场等级
                    for (RankEntry entry : rankArena.all()) {
                        if (num >= 100) {
                            break;
                        }
                        String playerCode = entry.getKey();
                        PlayerBean playerBean = PlayerBean.get(playerCode);
                        if (playerBean == null || playerBean.getLevel() < funcion.getPlayerlv()) {
                            continue;// 玩家等级不足不能参加
                        }
                        rankPlainsArena.put(playerCode);
                        num++;
                    }
                }
//				if (rankPlainsArena.size() >= 20) {
                open = true;
//				} else {
//					System.err.println("中原擂台活动没有开启，因为人数不足！" + DateTime.now().toString());
//				}
            }
        }
        if (open) {
            module.setCode(PlainsArenaModule.code(time));
            module.setOpening(true);
            System.err.println("中原擂台活动开始！！！" + DateTime.now().toString());
        }
    }

    private void settle(PlainsArenaModule module) {
        module.setOpening(false);
    }

    private void rewardRank(int areaGroupId) {
        System.err.println("中原擂台发赛季排名奖励了！！！！" + DateTime.now().toString());
        Map<String, plainsarena> arenadatas = DataCenter.getAllData(plainsarena.class);
        Map<Integer, ArrayList<RankEntry>> topMap = new HashMap<>();
        for (plainsarena arenadata : arenadatas.values()) {
            topMap.put(arenadata.getRank(), rewardTop(areaGroupId, arenadata.getRank()));
        }

        Map<String, plainsarenarankreward> all = DataCenter.getAllData(plainsarenarankreward.class);
        for (plainsarena arenadata : arenadatas.values()) {
            ArrayList<RankEntry> top = topMap.get(arenadata.getRank());
            for (plainsarenarankreward data : all.values()) {
                if (data.getRank() != arenadata.getRank()) {
                    continue;
                }
                Collection<Currency> rewards = Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum());

                for (int i = data.getRankingmin() - 1; i < data.getRankingmax() && i < top.size(); i++) {
                    int rank = i + 1;
                    RankEntry entry = top.get(i);
                    String title = GameString.中原擂台排行奖励_titl(rank).getText();
                    String content = GameString.中原擂台排行奖励_msg(rank).getText();
                    new MailHandle().sendMail(entry.getKey(), MailTypeEnum.Mail, title, content, CCReason.中原擂台, rewards);

                    ArenaRankPublisher.getInstance().publish(entry.getKey(), rank);
                }
            }
        }

    }

    private ArrayList<RankEntry> rewardTop(int areaGroupId, int level) {
        int min = -1;// 全局最小
        int max = -1;// 全局最大
        Map<String, plainsarenarankreward> all = DataCenter.getAllData(plainsarenarankreward.class);
        for (plainsarenarankreward data : all.values()) {
            if (data.getRank() != level) {
                continue;
            }
            if (min < 0 || data.getRankingmin() < min) {
                min = data.getRankingmin();
            }
            if (max < 0 || data.getRankingmax() > max) {
                max = data.getRankingmax();
            }
        }
        RankPlainsArena rank = new RankPlainsArena(areaGroupId, level);
        return new ArrayList<>(rank.range(min, max));
    }


    // 阵容处理===========================================================================

    /**
     * 处理阵容信息
     *
     * @param formatNum
     */
    public FormatMessageEntry packFormatInfo(PlainsArenaPlayerModule playerModule, int formatNum, boolean isAll) {
        String playerCode = playerModule.getPlayerCode();
        HashMap<String, Hero> heros = new HashMap<>();
        FormatMessageEntry entry = new FormatMessageEntry();

        int i = 0;
        for (Format format : playerModule.getFormat()) {
            FormatMessage.Format.Builder formatBuilder = FormatMessage.Format.newBuilder();

            ArrayList<Hero> formatHeroList = new ArrayList<>();
            Hero herofu = Hero.get(playerCode, format.getFu());
            if (format.getFu() != null && herofu != null) {
                heros.put(herofu.getCode(), herofu);
                formatHeroList.add(herofu);
                formatBuilder.setFU(format.getFu());
            }

            Hero herofm = Hero.get(playerCode, format.getFm());
            if (format.getFm() != null && herofm != null) {
                heros.put(herofm.getCode(), herofm);
                formatHeroList.add(herofm);
                formatBuilder.setFM(format.getFm());
            }

            Hero herofd = Hero.get(playerCode, format.getFd());
            if (format.getFd() != null && herofd != null) {
                heros.put(herofd.getCode(), herofd);
                formatHeroList.add(herofd);
                formatBuilder.setFD(format.getFd());
            }

            Hero herobu = Hero.get(playerCode, format.getBu());
            if (format.getBu() != null && herobu != null) {
                heros.put(herobu.getCode(), herobu);
                formatHeroList.add(herobu);
                formatBuilder.setBU(format.getBu());
            }

            Hero herobm = Hero.get(playerCode, format.getBm());
            if (format.getBm() != null && herobm != null) {
                heros.put(herobm.getCode(), herobm);
                formatHeroList.add(herobm);
                formatBuilder.setBM(format.getBm());
            }

            Hero herobd = Hero.get(playerCode, format.getBd());
            if (format.getBd() != null && herobd != null) {
                heros.put(herobd.getCode(), herobd);
                formatHeroList.add(herobd);
                formatBuilder.setBD(format.getBd());
            }

            formatBuilder.setNB(format.getNb());
            entry.addFormat(formatBuilder.build());

            //从缓存获取
            long totalPower = 0;
            for (Hero hero : formatHeroList) {
                if (hero.getPower() != null) {
                    totalPower += hero.getPower();
                } else {
                    totalPower += new BattleHandle().calculatePower(playerCode, hero, format);
                }
            }

            entry.getFormatPower().add(totalPower);

            if (formatNum > 0 && ++i >= formatNum) {
                break;
            }
        }

        HeroHandle module = new HeroHandle();
        if (isAll) {
            LinkedList<HeroMessage.HeroSimple> heroSimples = new LinkedList<>();
            for (Hero hero : Hero.all(playerCode).values()) {
                heroSimples.add(module.getHeroSimple(playerCode, hero));
            }
            entry.addHero(playerCode, heroSimples);

        } else {
            LinkedList<HeroMessage.HeroSimple> heroSimples = new LinkedList<>();
            for (Hero hero : heros.values()) {
                heroSimples.add(module.getHeroSimple(playerCode, hero));
            }
            entry.addHero(playerCode, heroSimples);
        }

        return entry;
    }

    static private class FormatMessageEntry {
        private ArrayList<FormatMessage.Format> formats;
        private ArrayList<HeroMessage.HeroSimple> heros;
        private ArrayList<Long> formatPower;

        private FormatMessageEntry() {
            formats = new ArrayList<>();
            heros = new ArrayList<>();
            formatPower = new ArrayList<>();
        }

        private ArrayList<FormatMessage.Format> getFormats() {
            return formats;
        }

        private ArrayList<HeroMessage.HeroSimple> getHeros() {
            return heros;
        }

        public ArrayList<Long> getFormatPower() {
            return formatPower;
        }

        public void addFormat(FormatMessage.Format format) {
            formats.add(format);
        }

        private void addHero(String playerCode, LinkedList<HeroMessage.HeroSimple> list) {
//            heros.add(new HeroHandle().getHeroSimple(playerCode, hero));
            heros.addAll(list);
        }

    }

    /**
     * 领宝箱
     */
    public Result box(String playerCode, int box, PlainsArenaMessage.PlainsArenaBoxResponse.Builder response) {
        plainsarenasignreward data = DataCenter.getData(box, plainsarenasignreward.class);
        if (data == null) {
            return Result.ParamError;// 宝箱id错误
        }
        PlainsArenaPlayerModule playerModule = PlainsArenaPlayerModule.get(playerCode);
        if (playerModule == null) {
            return Result.ModuleNotOpen;
        }
        if (data.getRank() != playerModule.getLevel()) {
            return Result.ParamError;// 宝箱段位不符
        }
        if (data.getCondition() > playerModule.getWins()) {
            return Result.PlainsArenaBoxCantGet;// 宝箱领取条件不足
        }
        if (playerModule.getBox().contains(data.getCode())) {
            return Result.PlainsArenaBoxHasGet;// 宝箱已领取
        }

        try {
            if (playerModule.tryLock()) {
                Currency reward = Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum());
                new CurrencyHandle().addCurrency(playerCode, CCReason.中原擂台, reward);

                playerModule.getBox().add(data.getCode());
                playerModule.set();

                response.setBox(box);
                response.addAllRewards(new CurrencyHandle().packItems(reward));
            }
        } catch (Exception e) {
            return Result.DataError;
        } finally {
            playerModule.unlock();
        }
        return Result.Success;
    }

    public Result levelReward(String playerCode, int level, PlainsArenaMessage.PlainsArenaLevelRewardResponse.Builder response) {
        plainsarenareward data = DataCenter.getData(level, plainsarenareward.class);
        if (data == null) {
            return Result.ParamError;// 奖励id错误
        }
        PlainsArenaPlayerModule playerModule = PlainsArenaPlayerModule.get(playerCode);
        if (playerModule == null) {
            return Result.ModuleNotOpen;
        }
        if (data.getCondition() > playerModule.getLevel()) {
            return Result.ParamError;// 奖励段位不符
        }
        if (playerModule.getLevelBox().contains(data.getCode())) {
            return Result.PlainsArenaLevelRewardGet;// 奖励已领取
        }
        try {
            if (playerModule.tryLock()) {
                Currencies rewards = new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));
                new CurrencyHandle().addCurrency(playerCode, CCReason.中原擂台, rewards);

                playerModule.getLevelBox().add(data.getCode());
                playerModule.set();

                response.setLevel(level);
                response.addAllRewards(new CurrencyHandle().packItems(rewards));
            }
        } catch (Exception e) {
            return Result.DataError;
        } finally {
            playerModule.unlock();
        }
        return Result.Success;
    }

    /**
     * 购买挑战次数
     * @param playerModule
     * @param times 要购买的次数
     * @return
     */
    public Result buyTimes (PlainsArenaPlayerModule playerModule, int times) {
        try {
            if (playerModule.tryLock()) {
                int price = playerModule.getBuyTimesPrice(playerModule);
                Currency cost = Currency.create(CurrencyType.CT_元宝, 0, price * times);
                try {
                    new CurrencyHandle().cost(playerModule.getPlayerCode(), CCReason.中原擂台, cost);
                    playerModule.setBuyAmount(playerModule.getBuyAmount() + 1);
                    playerModule.setBuyTimes(playerModule.getBuyTimes() + times);
                    playerModule.set();
                } catch (CurrencyNotEnoughException e) {
                    return new Result(Result.CostFail, e.getType().getNumber(), e.getDataId());// 消费不足
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.DataError;
        } finally {
            playerModule.unlock();
        }

        return Result.Success;
    }

}